﻿using System.IO;
using Microsoft.Kinect;
using DetectingKinectSencor;
using System.Windows;
using System;

namespace Kinect.Toolbox.Record
{
    /// <summary>
    /// The following class was provided by the book 
    /// Microsoft.Press.Programming.with.the.Kinect.for.Windows.Software.Development.Kit.Sep.2012
    /// </summary>
    public class PlayColorStream : FramePlayer
    {
        bool DEBUGon = MainWindow.DEBUGplayColorStream;
        bool DEBUGstreamWriterReplayOn = MainWindow.DEBUGstreamWriterReplay;

        readonly ColorImageFrame internalFrame;
        long streamPosition;
        Stream stream;

        public int Width { get; private set; }
        public int Height { get; private set; }
        public int BytesPerPixel { get; private set; }
        public ColorImageFormat Format { get; private set; }
        public int PixelDataLength { get; set; }

        /// <summary>
        /// Constructor of PlayColorStream
        /// </summary>
        /// <param name="frame"></param>
        public PlayColorStream(ColorImageFrame frame)
        {
            // The format of the frame is saved: RGB or RAW or YUV and the resolution
            Format = frame.Format;

            // Number of bytes per pixel is saved
            BytesPerPixel = frame.BytesPerPixel;

            // Frame number and timestamp is important for synchronisation, because it is only one stream
            // which is split during the replay
            frameNumber = frame.FrameNumber;
            timeStamp = frame.Timestamp;

            if (DEBUGon){
                Console.WriteLine("PlayColorStream Frame number: " + frameNumber);
                Console.WriteLine("PlayColorStream Time stamp: " + timeStamp);
                Console.WriteLine("\n");
            }   

            // Save width and height
            Width = frame.Width;
            Height = frame.Height;

            // Number of pixels of the frame
            PixelDataLength = frame.PixelDataLength;

            // Copy the frame
            internalFrame = frame;

        }

        /// <summary>
        /// The default constructor
        /// </summary>
        public PlayColorStream()
        {
        }
        

        /// <summary>
        /// Method which is invoked in PlayStreams AddFrame(BinaryReader), in PlayerSystem is than 
        /// the method CreateFromReader() invoked, dependent on the object type in PlayStreams.
        /// In this case it was invoked from a color object
        /// </summary>
        /// <param name="reader"></param>
        internal override void CreateFromReader(BinaryReader reader)
        {
            type = "color";

            // Save the timestamp, important for synchronisation with the other frames (depth, skeleton)
            timeStamp = reader.ReadInt64();

            if (DEBUGon)
                Console.WriteLine("CreateFromReader TimeStamp: " + timeStamp);
            // Save how much bytes are per pixel 
            BytesPerPixel = reader.ReadInt32();

            // Frame format is casted to ColorImageFormat
            Format = (ColorImageFormat)reader.ReadInt32();

            // Save width and height
            Width = reader.ReadInt32();
            Height = reader.ReadInt32();

            // Save frame number as well important for synchronisation
            frameNumber = reader.ReadInt32();

            if(DEBUGon)
                Console.WriteLine("CreateFromReader frame number: " + frameNumber);

            // Number of pixels per frame
            PixelDataLength = reader.ReadInt32();

            // Get access to the base stream
            stream = reader.BaseStream;

            // Get current position in stream
            streamPosition = stream.Position;

            if(DEBUGon)
                Console.WriteLine("CreateFromReader stream position: " + streamPosition );

            // Move the position in the stream by the pixelDataLength
            stream.Position += PixelDataLength;
        }

        /// <summary>
        /// Copies the pixelData to the local internalFrame
        /// </summary>
        /// <param name="pixelData"></param>
        public void CopyPixelDataTo(byte[] pixelData)
        {
            if (internalFrame != null)
            {
                internalFrame.CopyPixelDataTo(pixelData);
                return;
            }

            // Save the current position
            long savedPosition = stream.Position;

            // Change current position to the stream position
            stream.Position = streamPosition;
            stream.Read(pixelData, 0, PixelDataLength);

            // Change back the current position to the savedPosition
            stream.Position = savedPosition;
        }

        /// <summary>
        /// This mehod is important to play later live streams and saved streams without any change
        /// Implicitly without an cast operator, is the ColorImageFrame casted to a PlayColorStream
        /// </summary>
        /// <param name="frame"></param>
        /// <returns></returns>
        public static implicit operator PlayColorStream(ColorImageFrame frame)
        {
            return new PlayColorStream(frame);
        }
    }

    
}